
//using UnityEngine;
//using System;
//using System.Collections.Generic;
//using System.Text;

//namespace GCommon
//{
//    public class SpawnPool
//    {
//        Queue<UnityEngine.Object> m_FreeList = new Queue<UnityEngine.Object>();
//        GameObject m_Parent = null;
//        ResourceID m_resID;
//        Vector3 m_ResourceOrgScale = Vector3.one;
//        private int m_GetResTimesTotal = 0;
//        private int m_ReturnResTimesTotal = 0;
//        private int m_PoolSizeDynamicMax = 0;
//        private int m_InstanceNewResTimes = 0;
//        List<UnityEngine.Object> m_ActiveList;
//        private uint m_LimitMaxPoolSize = 0;

//        public SpawnPool(GameObject parent, ResourceID id)
//        {
//            m_resID = id;
//            m_Parent = parent;
//        }

//        public void InitPool(ResourceID id, int num, uint maxSize = 0)
//        {
//            m_LimitMaxPoolSize = maxSize;
//            int actualNum = maxSize == 0 ? num : (int)Mathf.Min(num, maxSize);
//            int count = m_FreeList.Count;

//            UnityEngine.Object objReference = ResourceManager.instance.GetResource(m_resID);
//            for (int i = 0; i < actualNum - count; i++)
//            {
//                if (objReference != null)
//                {
//                    UnityEngine.Object freeObject = ResourceManager.Instant(objReference);
//                    GameObject freeGO = freeObject as GameObject;
//                    freeGO.transform.SetParent(m_Parent.transform);
//                    freeGO.SetActive(false);
//                    HandleResEnqueue(freeObject);
//                }
//            }
//        }

//        public UnityEngine.Object GetRes(Transform parentTrans)
//        {
//            UnityEngine.Object freeObject = null;
//            bool isNewGameObject = false;
//            if (m_FreeList.Count > 0)
//            {
//                freeObject = m_FreeList.Dequeue();
//            }

//            if (freeObject == null)
//            {
//                if (m_ActiveList != null && m_ActiveList.Count > 0 && m_ActiveList.Count == m_LimitMaxPoolSize)
//                {

//                    freeObject = m_ActiveList[0];
//                    m_ActiveList.RemoveAt(0);
//                }
//                else
//                {
//                    UnityEngine.Object objReference = ResourceManager.instance.GetResource(m_resID);
//                    if (objReference != null)
//                    {
//                        freeObject = ResourceManager.Instant(objReference);
//                        isNewGameObject = true;
//                    }
//                }
//            }

//            HandleObject(isNewGameObject, freeObject, parentTrans);
//            return freeObject;
//        }

//        private void HandleObject(bool isNew, UnityEngine.Object obj, Transform parentTrans)
//        {
//            GameObject freeGO = obj as GameObject;

//            if (freeGO != null)
//            {
//                if (isNew)
//                {
//                    m_ResourceOrgScale = freeGO.transform.localScale;
//                    m_InstanceNewResTimes++;
//                }

//                freeGO.transform.SetParent(parentTrans);
//                freeGO.SetActive(true);
//                ReusableObject ro = freeGO.GetComponent<ReusableObject>();
//                //Debug.Assert(ro != null);
//                if (ro != null)
//                {
//                    ro.ResID = m_resID;
//                    if (!isNew)
//                    {
//                        ro.TemporyStopUsing();
//                    }

//                    ro.Prepare();
//                    if (m_LimitMaxPoolSize > 0)
//                    {
//                        if (m_ActiveList == null)
//                        {
//                            m_ActiveList = new List<UnityEngine.Object>();
//                        }
//                        m_ActiveList.Add(obj);
//                    }
//                }
//            }

//            m_GetResTimesTotal++;
//        }

//        #region GetResAsync
//        private class AsyncRequest
//        {
//            public Transform Parent;
//            public int Count = 1;
//            public bool IsForInit = false;
//            public Action<bool, UnityEngine.Object> Callback;
//        }

//        private readonly List<AsyncRequest> mAsyncRequestList = new List<AsyncRequest>();
//        private readonly List<AsyncRequest> mAsyncRequestPool = new List<AsyncRequest>();
//        private uint mCurAsyncResLoadTicket = 0;

//        private void RecycleRequest(AsyncRequest request)
//        {
//            request.Parent = null;
//            request.Callback = null;
//            request.Count = 1;
//            request.IsForInit = false;
//            mAsyncRequestPool.Add(request);
//        }

//        private AsyncRequest GetAsyncRequest()
//        {
//            var count = mAsyncRequestPool.Count;
//            if (count > 0)
//            {
//                var req = mAsyncRequestPool[count - 1];
//                mAsyncRequestPool.RemoveAt(count - 1);
//                return req;
//            }
//            else
//            {
//                return new AsyncRequest();
//            }
//        }

//        public void InitPoolAsync(ResourceID id, int num, uint maxSize = 0)
//        {
//            m_LimitMaxPoolSize = maxSize;
//            if (m_FreeList.Count < Mathf.Min(num, maxSize))
//            {
//                //if (mCurAsyncResLoadTicket == 0)
//                //    mCurAsyncResLoadTicket = ResourceManager.instance.GetResource(m_resID, HandleNewObject);

//                if (mCurAsyncResLoadTicket != 0)
//                {
//                    var req = GetAsyncRequest();
//                    req.Parent = null;
//                    req.Count = num;
//                    req.IsForInit = true;
//                    req.Callback = null;
//                    mAsyncRequestList.Add(req);
//                }

//            }
//        }

//        /// <summary>
//        /// Asynchronous version of GetRes
//        /// </summary>
//        /// <param name="callback"></param>
//        /// <param name="parentTrans"></param>
//        /// <returns></returns>
//        public uint GetResAsync(Action<bool, UnityEngine.Object> callback, Transform parentTrans)
//        {
//            if (m_FreeList.Count > 0)
//            {
//                var freeObject = m_FreeList.Dequeue();
//                HandleObject(false, freeObject, parentTrans);
//                callback(true, freeObject);
//                return 0;
//            }

//            if (m_ActiveList != null && m_ActiveList.Count > 0 && m_ActiveList.Count == m_LimitMaxPoolSize)
//            {
//                var freeObject = m_ActiveList[0];
//                m_ActiveList.RemoveAt(0);
//                HandleObject(false, freeObject, parentTrans);
//                callback(true, freeObject);
//                return 0;
//            }

//            // ensure the same AsyncResLoad request won't be asked again.
//            //if (mCurAsyncResLoadTicket == 0)
//            //    mCurAsyncResLoadTicket = ResourceManager.instance.GetResource(m_resID, HandleNewObject);

//            if (mCurAsyncResLoadTicket != 0)
//            {
//                var req = GetAsyncRequest();
//                req.Parent = parentTrans;
//                req.Count = 1;
//                req.Callback = callback;
//                mAsyncRequestList.Add(req);
//            }

//            return mCurAsyncResLoadTicket;
//        }

//        public void CancelResAsync(uint reqTicket)
//        {
//            if (reqTicket != mCurAsyncResLoadTicket)
//                return;

//            for (int i = 0; i < mAsyncRequestList.Count; ++i)
//                RecycleRequest(mAsyncRequestList[i]);

//            mAsyncRequestList.Clear();
//            mCurAsyncResLoadTicket = 0;
//            //ResourceManager.instance.CancelAsyncResLoad(reqTicket, HandleNewObject);
//        }

//        private void HandleNewObject(bool succeeded, UnityEngine.Object resObj)
//        {
//            for (int i = 0; i < mAsyncRequestList.Count; ++i)
//            {
//                var req = mAsyncRequestList[i];
//                if (!succeeded || resObj == null)
//                {
//                    if (req.Callback != null)
//                        req.Callback(false, null);

//                    Debug.LogError("Get resource for SpawnPool failed! ResID: " + m_resID);
//                }
//                else
//                {
//                    if (req.IsForInit)
//                    {
//                        int num = req.Count - m_FreeList.Count;
//                        for (int j = 0; j < num; j++)
//                        {
//                            UnityEngine.Object freeObject = ResourceManager.Instant(resObj);
//                            GameObject freeGO = freeObject as GameObject;
//                            freeGO.transform.SetParent(m_Parent.transform);
//                            freeGO.SetActive(false);
//                            HandleResEnqueue(freeObject);
//                        }
//                    }
//                    else
//                    {
//                        var obj = ResourceManager.Instant(resObj);
//                        HandleObject(true, obj, req.Parent);
//                        req.Callback(obj != null, obj);
//                    }
//                }
//                RecycleRequest(req);
//            }

//            mAsyncRequestList.Clear();
//            mCurAsyncResLoadTicket = 0;
//        }
//        #endregion

//        public void RecycleRes(UnityEngine.Object obj, bool worldPositionStays = true)
//        {
//            if (obj != null)
//            {
//                HandleResEnqueue(obj);

//                GameObject go = obj as GameObject;
//                if (go != null && go.transform != null && m_Parent != null)
//                {
//                    go.SetActive(false);
//                    go.transform.SetParent(m_Parent.transform, worldPositionStays);
//                    go.transform.localScale = m_ResourceOrgScale;

//                }

//                if (m_FreeList.Count > m_PoolSizeDynamicMax)
//                {
//                    m_PoolSizeDynamicMax = m_FreeList.Count;
//                }

//                m_ReturnResTimesTotal++;
//            }
//        }

//        public void HandleResEnqueue(UnityEngine.Object obj)
//        {
//            if (m_ActiveList != null)
//            {
//                m_ActiveList.Remove(obj);
//            }
//            if (m_LimitMaxPoolSize > 0 && m_FreeList.Count == m_LimitMaxPoolSize)
//            {
//                GameObject.Destroy(obj);
//            }
//            else
//            {
//                m_FreeList.Enqueue(obj);
//            }
//        }

//        public void Clear()
//        {
//            foreach (var free in m_FreeList)
//            {
//                if (free != null)
//                    GameObject.Destroy(free);
//            }
//            m_FreeList.Clear();
//            if (m_ActiveList != null)
//            {
//                m_ActiveList.Clear();
//            }
//            m_GetResTimesTotal = 0;
//            m_ReturnResTimesTotal = 0;
//            m_PoolSizeDynamicMax = 0;
//            m_InstanceNewResTimes = 0;
//        }

//        public void Destroy()
//        {
//            Clear();
//        }

//        public string GetPoolStatusAnalyseString()
//        {
//            StringBuilder sb = new StringBuilder();
//            sb.Append("ResID=").Append(ResourceManager.instance.GetResourceIDName(m_resID));
//            sb.Append(" GetResTimes=").Append(m_GetResTimesTotal);
//            sb.Append(" ReturnResTimes=").Append(m_ReturnResTimesTotal);
//            sb.Append(" PoolSizeMax=").Append(m_PoolSizeDynamicMax);
//            sb.Append(" InstanceNewResTimes=").Append(m_InstanceNewResTimes);
//            return sb.ToString();
//        }
//    }

//    public static class PoolManager
//    {
//        private static Dictionary<ResourceID, SpawnPool> m_ResPool =
//            new Dictionary<ResourceID, SpawnPool>();
//        private static GameObject m_Parent = null;

//        public static void InitRes(ResourceID resID, int num, uint maxSize = 0)
//        {
//            if (m_Parent == null)
//            {
//                m_Parent = new GameObject("PoolManager");
//                m_Parent.SetActive(false);
//            }
//            SpawnPool spawnPool = null;
//            if (!m_ResPool.TryGetValue(resID, out spawnPool))
//            {
//                spawnPool = new SpawnPool(m_Parent, resID);
//                m_ResPool[resID] = spawnPool;
//            }

//            if (spawnPool != null)
//            {
//#if RESLOAD_TRACK
//                string path = ResourceManager.instance.GetPathWithQuality(resID);
//                if (path != string.Empty)
//                {
//                    var stats = ResourceManager.instance.GetResLoadStats(path);
//                    stats.TimesFromPool++;
//                    ResourceManager.instance.IsResLoadFromPoolMgr = true;
//                }
//#endif
//                spawnPool.InitPool(resID, num, maxSize);
//#if RESLOAD_TRACK
//                ResourceManager.instance.IsResLoadFromPoolMgr = false;
//#endif
//            }
//        }

//        public static UnityEngine.Object GetRes(ResourceID resID, Transform parentTrans = null)
//        {
//            if (m_Parent == null)
//            {
//                m_Parent = new GameObject("PoolManager");
//                m_Parent.SetActive(false);
//            }
//            SpawnPool spawnPool;
//            if (!m_ResPool.TryGetValue(resID, out spawnPool))
//            {
//                spawnPool = new SpawnPool(m_Parent, resID);
//                m_ResPool[resID] = spawnPool;
//            }
//#if RESLOAD_TRACK
//            string path = ResourceManager.instance.GetPathWithQuality(resID);
//            if (path != string.Empty)
//            {
//                var stats = ResourceManager.instance.GetResLoadStats(path);
//                stats.TimesFromPool++;
//                ResourceManager.instance.IsResLoadFromPoolMgr = true;
//            }
//#endif
//            var obj = spawnPool.GetRes(parentTrans);
//#if RESLOAD_TRACK
//            ResourceManager.instance.IsResLoadFromPoolMgr = false;
//#endif
//            return obj;
//        }

//        /// <summary>
//        /// The asynchronous version PoolGetRes.
//        /// </summary>
//        /// <param name="resID"></param>
//        /// <param name="callback"></param>
//        /// <param name="parentTrans"></param>
//        /// <returns>
//        /// An uint identifier which you can use to cancel the async resource loading.
//        /// 0 value means this resource has already been loaded or it's a failure call.
//        /// You can check the bool flag and the object in the callback.
//        /// </returns>
//        public static uint GetRes(ResourceID resID, Action<bool, UnityEngine.Object> callback, Transform parentTrans = null)
//        {
//            if (callback == null)
//                return 0;

//            if (m_Parent == null)
//            {
//                m_Parent = new GameObject("PoolManager");
//                m_Parent.SetActive(false);
//            }
//            SpawnPool spawnPool;
//            if (!m_ResPool.TryGetValue(resID, out spawnPool))
//            {
//                spawnPool = new SpawnPool(m_Parent, resID);
//                m_ResPool[resID] = spawnPool;
//            }

//            if (false)
//                return spawnPool.GetResAsync(callback, parentTrans);
//            else
//            {
//                var obj = spawnPool.GetRes(parentTrans);
//                callback(obj != null, obj);
//                return 0;
//            }
//        }

//        public static void CancelResAsync(ResourceID resID, uint reqTicket)
//        {
//            SpawnPool spawnPool;
//            if (m_ResPool.TryGetValue(resID, out spawnPool))
//                spawnPool.CancelResAsync(reqTicket);
//        }

//        public static bool RecyleRes(ResourceID resID, UnityEngine.Object obj, bool worldPositionStays = true)
//        {
//            SpawnPool spawnPool;
//            if (!m_ResPool.TryGetValue(resID, out spawnPool))
//            {
//                Debug.LogWarning("poolmanager recycle can't find pool for " + resID);
//                return false;
//            }
//            spawnPool.RecycleRes(obj, worldPositionStays);
//            return true;
//        }

//        public static bool CleanPool(ResourceID resID)
//        {
//            // Use TryGetValue to avoid KeyNotFoundException.
//            //   This is faster than Contains() and then accessing the dictionary
//            SpawnPool spawnPool;
//            if (!m_ResPool.TryGetValue(resID, out spawnPool))
//            {
//                return false;
//            }
//            spawnPool.Clear();
//            return true;
//        }

//        public static void ClearAll()
//        {
//#if !LIVE_BUILD
//            //Debugger.LogError(GetPoolDebugInfo());
//#endif
//            foreach (KeyValuePair<ResourceID, SpawnPool> pair in m_ResPool)
//            {
//                pair.Value.Destroy();
//            }

//            m_ResPool.Clear();
//            if (m_Parent)
//            {
//                GameObject.Destroy(m_Parent);
//                m_Parent = null;
//            }
//        }

//        public static string GetPoolDebugInfo()
//        {
//            StringBuilder sb = new StringBuilder();
//            foreach (KeyValuePair<ResourceID, SpawnPool> pair in m_ResPool)
//            {
//                sb.Append(pair.Value.GetPoolStatusAnalyseString());
//                sb.Append("\n");
//            }

//            return sb.ToString();
//        }

//#if !LIVE_BUILD
//        public static string GetPoolDebugInfo(ResourceID resID)
//        {
//            SpawnPool pool = null;
//            if (m_ResPool.TryGetValue(resID, out pool))
//                return pool.GetPoolStatusAnalyseString();
//            else
//                return string.Empty;
//        }
//#endif
//    }
//}
